﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading;

namespace Client
{
    public partial class ChatDialog : Form
    {
        [DllImport("User32.dll")]
        protected static extern IntPtr SetClipboardViewer(IntPtr hWndNewViewer);

        [DllImport("User32.dll", CharSet = CharSet.Auto)]
        public static extern bool ChangeClipboardChain(IntPtr hWndRemove, IntPtr hWndNewNext);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

        private TcpClient messageConn;
        private TcpClient clipConn;
        private StreamWriter write;
        private IntPtr nextClipboardViewer;
        private BinaryWriter bWrite;
        private String path;

        public ChatDialog(TcpClient Conn1)
        {
            InitializeComponent();
            messageConn = Conn1;
            path = null;
        }
        /// <summary>
        /// setto la connessione per la gestione della clipboard
        /// </summary>
        /// <param name="Conn2"></param>
        public void setConnection(TcpClient Conn2)
        {
            clipConn = Conn2;
        }

        /// <summary>
        /// invio di un messaggio da parte del client
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SendButtonClick(object sender, EventArgs e)
        {
            write = new StreamWriter(messageConn.GetStream());
            String tmp = text_send.Text;
            if (!tmp.Equals(""))
            {
                write.WriteLine(tmp);
                write.Flush();
                text_send.Text = "";
            }
        }

        /// <summary> 
        /// non permetto di chiudere la finestra di chat
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ChatDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
        }

        /// <summary>
        /// Scrittura di un messaggio su finestra chat
        /// </summary>
        /// <param name="message"></param>
        public void newChatMessage(String message)
        {
            text_received.AppendText(message + Environment.NewLine);
        }
        /// <summary>
        /// settaggio dataobject contenente la clipboard
        /// </summary>
        /// <param name="data"></param>
        public void setClipboard(DataObject data) 
        {
            Clipboard.SetDataObject(data, true, 5, 100);
            if (path != null)
            {
                File.Delete(path);
                path = null;
            }
            if (data.ContainsFileDropList())
            {
                object tmp = data.GetData(DataFormats.FileDrop, true);
                path = ((String[])tmp)[0];
            }
        }

        /// <summary>
        /// invio della clipboard
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ClipButton_Click(object sender, EventArgs e)
        {
            String type = null;
            Object tmp = null;
            byte[] buffer = null;
            String filePath = null;
            bWrite = new BinaryWriter(clipConn.GetStream());
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
            try
            {
                if (Clipboard.ContainsFileDropList())
                {
                    IDataObject fileData = Clipboard.GetDataObject();
                    tmp = fileData.GetData(DataFormats.FileDrop, true);
                    filePath = ((String[])tmp)[0];
                    buffer = File.ReadAllBytes(filePath);
                    type = filePath.Substring(filePath.LastIndexOf("\\")).Replace("\\", "");
                    text_received.AppendText(Environment.NewLine + "--CLIPBOARD CONTENT " + type + " SENT--" + Environment.NewLine);
                }
                else
                {
                    using (MemoryStream ms = new MemoryStream())
                    {
                        if (Clipboard.ContainsText())
                        {
                            tmp = Clipboard.GetData(DataFormats.Text);
                            type = DataFormats.Text;
                        }
                        else if (Clipboard.ContainsImage())
                        {
                            tmp = Clipboard.GetData(DataFormats.Bitmap);
                            type = DataFormats.Bitmap;
                        }
                        bf.Serialize(ms, tmp);
                        buffer = ms.ToArray();
                        text_received.AppendText(Environment.NewLine + "--CLIPBOARD CONTENT " + type + " SENT--" + Environment.NewLine);
                    }
                }
                bWrite.Write(type);
                bWrite.Write(buffer.Length);
                bWrite.Write(buffer);
                bWrite.Flush();
            }
            catch (Exception ecc)
            {
                MessageBox.Show(ecc.ToString());
                return;
            }
        }
        
        /// <summary>
        /// cattura di messaggi del so riguardo la clipboard
        /// </summary>
        /// <param name="m"></param>
        protected override void WndProc(ref Message mess)
        {
            const int WM_DRAWCLIPBOARD = 0x308;
            const int WM_CHANGECBCHAIN = 0x030D;

            switch (mess.Msg)
            {
                case WM_DRAWCLIPBOARD:
                    try
                    {
                        if ((Clipboard.ContainsImage()) || (Clipboard.ContainsText()) || (Clipboard.ContainsFileDropList()))
                        {
                            ClipButton.Enabled = true;
                        }
                        else 
                        {
                            ClipButton.Enabled = false;
                        }
                    }
                    catch (ExternalException)
                    {
                    }
                    finally
                    {
                        SendMessage(nextClipboardViewer, mess.Msg, mess.WParam, mess.LParam);
                    }
                    break;
                case WM_CHANGECBCHAIN:
                    if (mess.WParam == nextClipboardViewer)
                        nextClipboardViewer = mess.LParam;
                    SendMessage(nextClipboardViewer, mess.Msg, mess.WParam, mess.LParam);
                    break;

                default:
                    base.WndProc(ref mess);
                    break;
            }
        }

        private void ChatDialog_Load(object sender, EventArgs e)
        {
            nextClipboardViewer = SetClipboardViewer(this.Handle);
        }


        private void ChatDialog_Resize(object sender, EventArgs e)
        {
            text_received.Width = ClientSize.Width - 2 * text_received.Left;
            text_received.Height = ClientSize.Height - 2 * text_received.Left - 7 - text_send.Height;
            Point textSendLoc = text_send.Location;
            textSendLoc.Y = ClientSize.Height - text_send.Left - text_send.Height;
            text_send.Location = textSendLoc;
            text_send.Width = ClientSize.Width - 72 - SendButton.Width - 2 * text_send.Left;
            Point sendButtonLoc = SendButton.Location;
            sendButtonLoc.X = textSendLoc.X + text_send.Width + 2;
            sendButtonLoc.Y = textSendLoc.Y - 2;
            SendButton.Location = sendButtonLoc;
            Point clipButtonLoc = ClipButton.Location;
            clipButtonLoc.X = textSendLoc.X + text_send.Width + 74;
            clipButtonLoc.Y = textSendLoc.Y - 2;
            ClipButton.Location = clipButtonLoc;
        }

        public void ReleaseClipboard()
        {
            ChangeClipboardChain(this.Handle, nextClipboardViewer);
            if (path != null)
            {
                File.Delete(path);
                path = null;
            }
        }
    }
}